import copy
import math
import random
import traceback

from db import utils
from logger import logger
from sub_events.base_event import BaseEvent, CHECK_RESULT_FAIL, CHECK_RESULT_PASS

LOGGER = logger.CustomLogger()


class CheckComments(BaseEvent):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.event_name_zh: str = "检视意见检查"
        self.event_name_en: str = "Review Comments Check"

        self.addition_count_threshold = self.cfg.get("sub_events", {}).get("check_comment_count", {}).get(
            "addition_count_threshold")
        self.comment_count_per_threshold = self.cfg.get("sub_events", {}).get("check_comment_count", {}).get(
            "comment_count_per_threshold")

        self.addition_count = 0
        self.expect_comments_count = 0
        self.actual_comments_count = 0
        self.max_comments_count = 10

    def generate_table(self) -> str:
        check_result = [
            {
                "code additions": self.addition_count,
                "result": CHECK_RESULT_FAIL if self.actual_comments_count < self.expect_comments_count else CHECK_RESULT_PASS,
                "review comments count(actual/expect)": "%d/%d" % (
                    self.actual_comments_count, self.expect_comments_count),
            }
        ]
        return self.generate_html_table(check_result, caption="%s(%s)" % (self.event_name_zh, self.event_name_en))

    def get_addition_count(self, pr_number):
        params = {'access_token': self.get_admin_token()}
        files = self.git_client.get_files(pr_number, params)
        for f in files:
            if "examples" not in f['filename'] and ".gitee" not in f['filename'] and ".gitcode" not in f['filename']:
                self.addition_count += int(f.get('additions', 0))

    def pre_execute(self) -> bool:
        self.get_addition_count(self.hook.pr_number)
        return self.addition_count > 20

    def check_comment_count(self):
        tokens = copy.deepcopy(self.cfg.get("sub_events", {}).get("check_comment_count", {}).get("tokens", []))
        token = None
        try:
            choice_count = len(tokens)
            # 从tokens中随机选择一个token访问
            index = random.randint(0, choice_count - 1)
            token = tokens[index]
            response = self.git_client.get_comments(self.hook.pr_number, token)
            self.actual_comments_count = len(response)
            self.failed = self.actual_comments_count < self.expect_comments_count
            return True
        except Exception as e:
            stack_str = traceback.format_exc()
            if token in tokens:
                tokens.remove(token)
            LOGGER.error(f"[{self.hook.pr_number}] get comments failed, details: {str(e)}, traceback:\n{stack_str}")
        return False

    def execute(self):
        """
        检查检视意见数量是否达标
        """
        self.expect_comments_count = \
            math.ceil(self.addition_count / self.addition_count_threshold) * self.comment_count_per_threshold
        if self.expect_comments_count > self.max_comments_count:
            self.expect_comments_count = self.max_comments_count
        force_status = utils.get_force_pass_status_by_hook(self.hook, "comments")
        if force_status:
            return
        if not self.check_comment_count():
        # if True:
            self.failed = True
            self.comment = self.generate_table() + "\n\n"
            self.comment += "本次检查由于内部原因实际未能成功执行，遇到此情况请勿执行\"self check\"，该检查也会执行不成功。\n" \
                            "请确保检视意见数符合要求后联系以下人员评论\"force comments\"进行消分，防止加分失败。\n"
            self.comment += ("The check was not successfully performed due to internal reasons. Please contact the "
                             "following members to leave a \"force comments\" comment before review in case review fails.\n"
                             "And do not leave a \"self check\" comment because it will fail too.\n")
            for member, name in self.cfg.get("sub_events", {}).get("check_comment_count", {}).get("force_accounts").items():
                self.comment += f"{name}: @{member.split('/')[-1]}\n"
        elif self.failed:
            table = self.generate_table()
            suggestion = "检视意见数量未达标（详情见上述表格），请联系组内成员积极进行代码检视。\n\n"
            suggestion += "The count of review comments falls short of the target (as detailed in the table above)." + \
                "Please contact your team to actively review your code."
            self.comment = table + "\n\n" + suggestion
